package asteroids.model.programs.statements;

import asteroids.model.programs.Program;
import asteroids.model.programs.expressions.Expression;
import asteroids.model.programs.statements.ProgramStatements.SequenceStatement;

/**
 * An abstract superclass for all statements in the Asteroids-project for OGP.
 * 
 * @author Michiel De Cuyper
 * @version 08.05
 * 
 */
public abstract class Statement {

	/**
	 * Constructor for the Statement class.
	 * 
	 * @param line
	 *            The line on which this statement is found
	 * @param column
	 *            The column in which this statement in found
	 */
	public Statement(int line, int column) {
		this.line = line;
		this.column = column;
		this.expression = null;
		this.nextStart = null;
	}

	/**
	 * Returns the line on which this statement is found on the text file.
	 * 
	 * @return ...
	 *         | return this.line
	 */
	public int getLine() {
		return this.line;
	}

	/**
	 * Returns the column on which this statement is found on the text file.
	 * 
	 * @return ...
	 *         | return this.column
	 */
	public int getColumn() {
		return this.column;
	}

	/**
	 * When a textfile is parsed, the 'line' and 'column' variables store the
	 * location of the found statement.
	 * These will be used for typechecks. These variables are final, as the
	 * location in the text file will not change.
	 */
	private final int line;
	private final int column;

	/**
	 * Executes this statement. Effects vary depending on which type of
	 * statement is called.
	 */
	public abstract void execute();

	/**
	 * Returns the program in which this statement is used
	 * 
	 * @return ...
	 *         | return this.program
	 */
	public Program getProgram() {
		return this.program;
	}

	/**
	 * Sets the program of this statement to a given statement.
	 * 
	 * @param program
	 *            The program to be set
	 * 
	 * @post ...
	 *       | this.getProgram == program
	 */
	public void setProgram(Program program) {
		this.program = program;
		linkExpression();
	}

	/**
	 * A program variable storing in which program this Statement is used.
	 */
	private Program program;

	/**
	 * Links an expression to a statement.
	 * 
	 * @effect ...
	 *         | expression.setStatement(this)
	 * @effect ...
	 *         | if (expression == null) return;
	 */
	private void linkExpression() {
		expression = this.getExpression();
		if (expression != null) {
			expression.setStatement(this);
		}
	}

	/**
	 * Returns the expression used in this Statement. Which expression is
	 * returned varies upon statement
	 */
	public abstract Expression getExpression();
	
	/**
	 * An expression variable storing the expression used in this statement.
	 * This can be e.g. the condition for an if- or while-statement.
	 */
	private Expression expression;
	
	public void setNextStart(SequenceStatement start){
		nextStart = start;
	}
	
	public SequenceStatement getNextStart(){
		return nextStart;
	}
	
	public abstract String typeCheckStatement(String errorMessage);
	
	private SequenceStatement nextStart;

}
